package com.mz.mattress.client.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.mz.mattress.api.common.Result;
import com.mz.mattress.api.entity.Device;
import com.mz.mattress.api.entity.OrderUseTimes;
import com.mz.mattress.api.entity.MattressMessageRecord;
import com.mz.mattress.api.enums.DeviceOptionEnum;
import com.mz.mattress.api.util.JacksonUtils;
import com.mz.mattress.client.api.resp.DeviceStatusResp;
import com.mz.mattress.client.mapper.DeviceMapper;
import com.mz.mattress.client.mapper.OrderUseTimesMapper;
import com.mz.mattress.client.mapper.MattressMessageRecordMapper;
import com.mz.mattress.client.service.MattressMsgService;
import com.mz.mattress.client.timer.WebSocketServer;

import com.mz.mattress.client.util.ParamUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Slf4j
public class MattressMsgServiceImpl implements MattressMsgService {

    @Autowired
    private MattressMessageRecordMapper mattressMessageRecordMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private OrderUseTimesMapper orderUseTimesMapper;

    @Autowired
    private WebSocketServer webSocketServer;

    //deviceCode
    private final static Map<String, DeviceStatusResp> MAP = new ConcurrentHashMap<>();

    //TimesId
    public final static Map<Integer, DeviceStatusResp> MAP_TIMES = new ConcurrentHashMap<>();

//    @Override
//    public void register(String deviceCode, Long memberId, Integer timesId) {
//
//        OrderUseTimes times = orderUseTimesMapper.selectById(timesId);
//        if (times == null) {
//            log.info("register_failed_wrong_timesId=" + timesId);
//            return;
//        }
//
//        DeviceStatusResp resp = MAP.get(deviceCode);
//        if (resp == null) {
//            resp = new DeviceStatusResp();
//            resp.setId(timesId);
//            resp.setMemberId(memberId);
//            resp.setDeviceCode(deviceCode);
//            resp.setEndTime(times.getEndTime());
//            MAP.putIfAbsent(deviceCode, resp);
//            MAP_TIMES.putIfAbsent(timesId, resp);
//            return;
//        }
//
//        if (resp.getId() != null && !resp.getId().equals(timesId)) {
//            resp.Reset();
//            resp.setId(timesId);
//            resp.setMemberId(memberId);
//            resp.setDeviceCode(deviceCode);
//            resp.setEndTime(times.getEndTime());
//            MAP.put(deviceCode, resp);
//            MAP_TIMES.put(timesId, resp);
//        }
//
//    }

    @Override
    public void register(Long memberId, OrderUseTimes times) {

        String deviceCode = times.getDeviceCode();
        Integer timesId = times.getId();

        DeviceStatusResp resp = MAP.get(deviceCode);
        if (resp == null) {
            resp = new DeviceStatusResp();
            resp.setId(timesId);
            resp.setMemberId(memberId);
            resp.setDeviceCode(deviceCode);
            resp.setEndTime(times.getEndTime());
            resp.setWorkMode(times.getMode());
            MAP.putIfAbsent(deviceCode, resp);
            MAP_TIMES.putIfAbsent(timesId, resp);
            return;
        }

        if (resp.getId() != null && !resp.getId().equals(timesId)) {
            resp.Reset();
            resp.setId(timesId);
            resp.setMemberId(memberId);
            resp.setDeviceCode(deviceCode);
            resp.setEndTime(times.getEndTime());
            resp.setWorkMode(times.getMode());
            MAP.put(deviceCode, resp);
            MAP_TIMES.put(timesId, resp);
        }
    }

    @Override
    public void unregister(String deviceCode) {

        DeviceStatusResp resp = MAP.get(deviceCode);
        if (resp != null) {

            MAP.remove(deviceCode);

            Integer timesId = resp.getId();
            if (timesId != null) {
                MAP_TIMES.remove(timesId);
            }

            toDb(resp);
        }
    }

    @Override
    public Result process(String message) {

        if (StringUtils.isEmpty(message)) {
            return Result.ok();
        }

        JsonNode obj = JacksonUtils.toObj(message);
        if (obj.get("method") == null) {
            log.info("message_method_is_null");
            return Result.ok();
        }

        String method = obj.get("method").textValue();
        String deviceCode = obj.get("deviceId").textValue();
        String data = obj.get("data").textValue();

        JsonNode dataObj = JacksonUtils.toObj(data);

        String dataMethod = dataObj.get("method").textValue();
        String productKey = dataObj.get("productKey").textValue();
        String bizType = dataObj.get("bizType").textValue();

        String dataContent = JacksonUtils.toJson(dataObj.get("data"));

        MattressMessageRecord record = new MattressMessageRecord();
        record.setDeviceCode(deviceCode);
        record.setProductKey(productKey);
        record.setMethod(method);
        record.setDataMethod(dataMethod);
        record.setDataContent(dataContent);
        mattressMessageRecordMapper.insert(record);

        DeviceStatusResp resp = MAP.get(deviceCode);
        if (resp == null) {
            //没有用户，更新设备状态
            if ("deviceStatus".equals(bizType)) {
                if ("heart".equals(dataMethod)) {
                    deviceMapper.updateHeart(deviceCode);
                } else if ("status".equals(dataMethod)) {
                    String status = dataObj.get("data").get("status").textValue();
                    //1online在线 0offline离线
                    Integer online = 0;
                    if ("online".equals(status)) {
                        online = 1;
                    }
                    deviceMapper.updateOnline(deviceCode, online);
                } else if ("sign".equals(dataMethod)) {
                    Integer sign = dataObj.get("data").get("deviceSign").asInt();
                    deviceMapper.updateSign(deviceCode, sign);
                }
            }
            return Result.ok();
        }

        Long memberId = null;
        if (dataObj.get("customerId") != null) {
            //如果有，优先使用报告的
            memberId = dataObj.get("customerId").longValue();
            if (memberId > 0) {
                resp.setMemberId(memberId);
            } else {
                memberId = resp.getMemberId();
            }
        } else {
            memberId = resp.getMemberId();
        }

        MAP_TIMES.putIfAbsent(resp.getId(), resp);

        if ("deviceStatus".equals(bizType)) {
            if ("heart".equals(dataMethod)) {
                resp.setOnline(1);
                deviceMapper.updateHeart(deviceCode);
            } else if ("status".equals(dataMethod)) {
                String status = dataObj.get("data").get("status").textValue();
                //1online在线 0offline离线
                Integer online = 0;
                if ("online".equals(status)) {
                    online = 1;
                }
                resp.setOnline(online);
                deviceMapper.updateOnline(deviceCode, online);
            } else if ("sign".equals(dataMethod)) {
                Integer sign = dataObj.get("data").get("deviceSign").asInt();
                resp.setSignal(sign);
                deviceMapper.updateSign(deviceCode, sign);
            }
        } else if ("service".equals(bizType)) {

            int code = dataObj.get("code").asInt();
            if (code == 200) {
                JsonNode content = dataObj.get("data").get("content");
                if (content == null) {
                    return Result.ok();
                }

                if (content.get(INSPECT_STATUS) != null) {
                    resp.setInspectStatus(content.get(INSPECT_STATUS).asInt());
                }

                if (content.get(RATE) != null) {
                    resp.setRate(content.get(RATE).asInt());
                }

                if (content.get(OXYGEN) != null) {
                    resp.setOxygen(content.get(OXYGEN).asInt());
                }

                if (content.get(CYCLE) != null) {
                    resp.setCycle(content.get(CYCLE).asInt());
                }

                if (content.get(TIRED) != null) {
                    resp.setTired(content.get(TIRED).asInt());
                }

                if (content.get(RESULTS) != null) {

                    int key = content.get(RESULTS).asInt();

//                    String resultName = ParamUtil.getInspectResultName(key);

                    resp.setResults(key);
                    //给出推荐模式
                    Integer mode = ParamUtil.getMode(key);

                    log.info("suggest_mode=" + mode);

                    resp.setSuggestMode(mode);
                    resp.setWorkMode(mode);

                }

                //当前工作状态
                if (content.get(WORK_STATUS) != null) {
                    int status = content.get(WORK_STATUS).asInt();
                    if (status < 2) {
                        resp.setWorkStatus(status);
                    }
                }

                if (content.get(WORK_MODE) != null) {
                    resp.setWorkMode(content.get(WORK_MODE).asInt());
                }

                if (content.get(STRENGTH) != null) {
                    resp.setStrength(content.get(STRENGTH).asInt());
                }

                if (content.get(TEMPER_SET) != null) {
                    resp.setTemper(content.get(TEMPER_SET).asInt());
                }

                if (content.get(TEMPER) != null) {
                    resp.setTemperCur(content.get(TEMPER).asInt());
                }

                if (content.get(VOLUME) != null) {
                    resp.setVolume(content.get(VOLUME).asInt());
                }

                String json = JacksonUtils.toJson(resp);
                log.info("websocket_resp=" + json);

                //发消息给前端
                webSocketServer.sendOneMessage(memberId.toString(), json);

                //updateWorkStatus
                updateInfo(deviceCode, memberId, resp);

            }

        }

        return Result.ok();
    }

    @Override
    public Result<DeviceStatusResp> deviceStatus(Integer timesId) {
        if (timesId == null) {
            return Result.ok();
        }
        DeviceStatusResp resp = MAP_TIMES.get(timesId);
        return Result.ok(resp);
    }

    @Override
    public void updateDeviceProperty(Integer timesId, String endTime, Integer status, DeviceOptionEnum optionEnum, Integer value) {

        DeviceStatusResp resp = MAP_TIMES.get(timesId);
        if (resp != null) {
            if (endTime != null) {
                resp.setEndTime(endTime);
            }
            if (status != null) {
                resp.setWorkStatus(status);
            }

            if (optionEnum != null) {

                if (optionEnum == DeviceOptionEnum.mode) {
                    resp.setWorkMode(value);
                } else if (optionEnum == DeviceOptionEnum.strength) {
                    resp.setStrength(value);
                } else if (optionEnum == DeviceOptionEnum.temper) {
                    resp.setTemper(value);
                } else if (optionEnum == DeviceOptionEnum.volume) {
                    resp.setVolume(value);
                }
            }

        }

    }

    private void updateInfo(String deviceCode, Long memberId, DeviceStatusResp resp) {

        Integer workStatus = resp.getWorkStatus();
        if (workStatus != null) {
            log.info("updateWorkStatus,workStatus=" + workStatus);
            deviceMapper.updateWorkStatus(deviceCode, workStatus);
        }

        Integer results = resp.getResults();
        if (results != null) {

            OrderUseTimes times = orderUseTimesMapper.selectOneByMemberIdDeviceCode(memberId, deviceCode);
            if (times == null) {
                log.info("no_find_device_use_times,memberId={},deviceCode={}", memberId, deviceCode);
                return;
            }

            OrderUseTimes update = new OrderUseTimes();
            update.setId(times.getId());
            update.setInspectStatus(resp.getInspectStatus());
            update.setRate(resp.getRate());
            update.setOxygen(resp.getOxygen());
            update.setCycle(resp.getCycle());
            update.setTired(resp.getTired());
            update.setResults(results);
            update.setResultName(ParamUtil.getInspectResultName(results));
            update.setMode(resp.getSuggestMode());

            orderUseTimesMapper.updateById(update);
        }
    }

    //保存设备信息
    private void toDb(DeviceStatusResp resp) {

        String deviceCode = resp.getDeviceCode();
        Device device = deviceMapper.selectByDeviceCode(deviceCode);
        if (device == null) {
            return;
        }

        Device update = new Device();
        update.setId(device.getId());
        update.setDeviceCode(deviceCode);
        if (resp.getTemper() != null) {
            update.setTemper(resp.getTemper());
        }
        if (resp.getTemperCur() != null) {
            update.setTemperCur(resp.getTemperCur());
        }
        if (resp.getVolume() != null) {
            update.setVolume(resp.getVolume());
        }
        if (resp.getStrength() != null) {
            update.setStrength(resp.getStrength());
        }
        deviceMapper.updateById(update);
    }

    @Override
    public Result processRecord(Integer id) {

        MattressMessageRecord record = mattressMessageRecordMapper.selectById(id);
//        JsonNode obj = JacksonUtils.toObj(record.getContent());

        return Result.ok();
    }

    @Override
    public void change() {

        List<MattressMessageRecord> list = mattressMessageRecordMapper.list();

        for (MattressMessageRecord record : list) {

//            String content = record.getContent();
//            JsonNode obj = JacksonUtils.toObj(content);
//            String method = obj.get("method").textValue();
//            String deviceId = obj.get("deviceId").textValue();
//            String data = obj.get("data").textValue();
//
//            MattressMessageRecord update = new MattressMessageRecord();
//            update.setId(record.getId());
//            update.setMethod(method);
//            update.setData(data);
//            update.setDeviceCode(deviceId);
//            mattressMessageRecordMapper.updateById(update);

        }
    }

    @Override
    public void changeData() {

        List<MattressMessageRecord> list = mattressMessageRecordMapper.listData();

        for (MattressMessageRecord record : list) {

//            String data = record.getData();
//            JsonNode obj = JacksonUtils.toObj(data);
//            String dataMethod = obj.get("method").textValue();
//            String productKey = obj.get("productKey").textValue();

//            JsonNode data1 = obj.get("data");
//            String json = JacksonUtils.toJson(data1);


//            MattressMessageRecord update = new MattressMessageRecord();
//            update.setId(record.getId());
//            update.setProductKey(productKey);
//            update.setDataMethod(dataMethod);
//            update.setDataContent(json);
//            mattressMessageRecordMapper.updateById(update);

        }

    }

    public static void main(String[] args) {

//        OrderUseTimes times = new OrderUseTimes();
//        times.setAge(44);
//        times.setDuration(4);
//        System.out.println(JacksonUtils.toJson(times));

        String key = "AA";

        DeviceStatusResp resp = new DeviceStatusResp();
        resp.setOnline(3);
        resp.setId(1);

        MAP.put(key, resp);
        MAP_TIMES.put(resp.getId(), resp);

        DeviceStatusResp resp1 = MAP.get(key);
        Integer online = resp1.getOnline();
        resp1.setCycle(3);
        System.out.println(online);
        resp1.setOnline(4);

        DeviceStatusResp resp2 = MAP.get(key);
        System.out.println(resp2.getOnline());

        DeviceStatusResp resp3 = MAP_TIMES.get(resp1.getId());
        System.out.println(resp3.getCycle());

    }


}